package com.hzncc.flowable_diboot.controller.flowable;

import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.JSON;
import com.diboot.core.vo.JsonResult;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author GaoGuoPei
 * @describe
 * @date 2024/3/21
 **/
@RestController
@RequestMapping("/flowable/flowchart")
public class DeployController {

    private final TaskService taskService;
    private final RepositoryService repositoryService;
    private final ProcessEngine processEngine;

    public DeployController(TaskService taskService, RepositoryService repositoryService, ProcessEngine processEngine) {
        this.taskService = taskService;
        this.repositoryService = repositoryService;
        this.processEngine = processEngine;
    }

    /**
     *  上传bpmn 文件发布流程
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/byUploadFile")
    public JsonResult byUploadFile(@RequestParam("file") MultipartFile file) throws Exception {
        String resourceName = file.getOriginalFilename();
        String substring = resourceName.substring(0,resourceName.indexOf('.', 0));
        Deployment deployStream = repositoryService.createDeployment()
                .name(substring)
                .addInputStream(resourceName, file.getInputStream())
                .deploy();
        return JsonResult.OK();
    }

    /**
     * 通过 processes 目录下的文件发布流程
     * @param params
     * @return
     * @throws Exception
     */
    @PostMapping("/byProcesses")
    public JsonResult byProcesses( @RequestBody Map<String, Object> params) throws Exception {
        Deployment deployClasspath = repositoryService.createDeployment()
                .name(params.get("name").toString())
                .addClasspathResource("processes/"+params.get("allName").toString())
                .deploy();
        return JsonResult.OK();
    }

    /**
     * 查询流程的部署信息
     * @return
     * @throws Exception
     */
    @PostMapping("/getList")
    public JsonResult getList() throws Exception {
        List<Deployment> deploymentList = repositoryService.createDeploymentQuery().list();
        /**
         *  精准查询    后续通过条件查询，传参使用下面的示例   分页也需要后续适配

         * 例如我想查询 key 为 javaboy的工作流key 的流程部署文件，但是这个流程我之前部署过多次（版本升级），现在我想查询最近一次的流程部署信息
         * Deployment deployment = repositoryService.createDeploymentQuery().deploymentKey("javaboy的工作流key").latest().singleResult();

         * 例如根据流程定义的 KEY 去查询所有的流程定义，这个 KEY 其实就是流程定义 XML 文件中的 id
         * List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("javaboy_submit_an_expense_account").list();

         *要是觉得用 API 查询 不过瘾，我们也可以自己写 SQL 查询。
         * 跟前面一样，例如我想查询 key 为 javaboy的工作流key 的流程部署文件，但是这个流程我之前部署过多次（版本升级），现在我想查询最近一次的流程部署信息，查询方式如下：
         * Deployment deployment = repositoryService.createNativeDeploymentQuery().sql("SELECT RES.* from ACT_RE_DEPLOYMENT RES WHERE RES.KEY_ = #{key} and RES.DEPLOY_TIME_ = (select max(DEPLOY_TIME_) from ACT_RE_DEPLOYMENT where KEY_ = RES.KEY_) order by RES.ID_ asc").parameter("key", "javaboy的工作流key").singleResult();

         */
        List<ReturnDeploymentVo> returnDeploymentVos = BeanUtils.convertList(deploymentList, ReturnDeploymentVo.class);
        for (ReturnDeploymentVo returnDeploymentVo : returnDeploymentVos) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(returnDeploymentVo.getId()).singleResult();
            returnDeploymentVo.setCategory(processDefinition.getCategory());
            returnDeploymentVo.setKey(processDefinition.getKey());
            returnDeploymentVo.setProcessDefinitionId(processDefinition.getId());
        }
        return JsonResult.OK(returnDeploymentVos);
    }

    /**
     * 删除已发布部署的流程
     * @Parameter  deploymentId  要删除的流程id    cascade  当流程已经启动之后开始相关任务了，是否 一并删除
     * @return
     * @throws Exception
     */
    @PostMapping("/delete")
    public JsonResult delete(@RequestParam String deploymentId, @RequestParam boolean cascade) throws Exception {
        repositoryService.deleteDeployment(deploymentId,cascade);
        return JsonResult.OK();
    }
}
